﻿using System;
using System.Collections.Generic;
using JTLeigh.Commerce.Spencer.Core.Service.Contracts;
using JTLeigh.Commerce.Spencer.Core.Testing;
using JTLeigh.Commerce.Spencer.Features.ProductFeedback.Service.Contracts.Runtime.GetProductFeedback;
using JTLeigh.Commerce.Spencer.Features.ProductFeedback.Service.Contracts.Runtime.GetProductFeedbackSnapshot;
using JTLeigh.Commerce.Spencer.Features.ProductFeedback.Service.Contracts.Runtime.GetProductFeedbackSummaries;
using JTLeigh.Commerce.Spencer.IntegrationTests.ProductFeedbackRuntimeService;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using GetProductFeedback_ProductRatingAttribute = JTLeigh.Commerce.Spencer.Features.ProductFeedback.Service.Contracts.Runtime.GetProductFeedback.ProductRatingAttribute;
using GetProductFeedback_ProductRecommendationAttribute = JTLeigh.Commerce.Spencer.Features.ProductFeedback.Service.Contracts.Runtime.GetProductFeedback.ProductRecommendationAttribute;
using GetProductFeedbackSnapshot_ProductRatingAttribute = JTLeigh.Commerce.Spencer.Features.ProductFeedback.Service.Contracts.Runtime.GetProductFeedbackSnapshot.ProductRatingAttribute;
using GetProductFeedbackSnapshot_ProductRecommendationAttribute = JTLeigh.Commerce.Spencer.Features.ProductFeedback.Service.Contracts.Runtime.GetProductFeedbackSnapshot.ProductRecommendationAttribute;

namespace JTLeigh.Commerce.Spencer.IntegrationTests
{

    /// <summary>
    /// Integration tests for the Product Feedback service.
    /// </summary>
    /// <remarks>
    /// <para>
    /// These test cases depend on data in the ProductFeedbackMetadata and ProductFeedback
    /// databases.
    /// </para>
    /// </remarks>
	[TestClass]
	public class ProductFeedbackRuntimeServiceFixture
	{

		#region Inner Classes and Types

		private static class Constants
		{

			public static class ProductRatingAttribute
			{

				public static class AttributeId
				{
					public static readonly Guid ImageQuality = new Guid("21828F07-BFF4-4c96-872A-D7CD055340E4");
					public static readonly Guid SoundQuality = new Guid("3A993AE2-BDB9-4336-B953-ABC19991C2FF");
					public static readonly Guid Design = new Guid("683D34A4-E844-4f25-BC7E-9B97E0E1E228");
					public static readonly Guid ValueForMoney = new Guid("C7B785E6-43A7-4abc-AE6E-635F9A06AB80");
				}

			}

			public static class ProductRecommendationAttribute
			{

				public static class AttributeId
				{
					public static readonly Guid FamilyMember = new Guid("B004E867-4876-403f-827E-D30852E81D7C");
					public static readonly Guid Friend = new Guid("A36552C6-59AE-4252-89B4-72109A9BF5C3");
					public static readonly Guid Coworker = new Guid("0593D7DB-CAA6-469f-AEEB-D5B65940ACD1");
				}

			}

			public static class ProductReviewAttribute
			{

				public static class AttributeId
				{
					public static readonly Guid Pros = new Guid("DEFD2F7D-8355-45d1-A4D9-796D9FCDDA11");
					public static readonly Guid Cons = new Guid("042A0ED1-0937-4f1d-94FD-BE342AD5231F");
					public static readonly Guid BottomLine = new Guid("4C8A96D1-30A0-4bf4-9B3F-CC2540FB19D8");
				}

			}

            public static class ProductReviewImage
            {

                public static class ImageId
                {
                    public static readonly Guid ProductInSunlight = new Guid("9365DA9F-2108-43B8-A885-71033F1B33D8");
                    public static readonly Guid ProductInLowLight = new Guid("D4455EC9-F785-47F1-B4F2-F2910FB228C0");
                    public static readonly Guid TerribleQuality = new Guid("CAEF6521-8F4F-4FA0-B871-53E3316A03C7");
                }

            }
        }

		#endregion // Inner Classes and Types

		#region Methods

        /// <summary>
        /// FIXME
        /// </summary>
		[TestMethod]
		public void TestGetProductFeedbackEnglish()
		{
			ProductFeedbackRuntimeServiceClient client;
			GetProductFeedbackRequest request;
			GetProductFeedbackResponse response;
			ProductFeedback feedback;
			ProductRatingAttributeValue ratingAttributeValue;
			ProductRecommendationAttributeValue recommendationAttributeValue;
			ProductReviewAttributeValue reviewAttributeValue;
			GetProductFeedback_ProductRatingAttribute ratingAttribute;
			GetProductFeedback_ProductRecommendationAttribute recommendationAttribute;
			ProductReviewAttribute reviewAttribute;
            ProductReviewImage reviewImage;

            using (client = new ProductFeedbackRuntimeServiceClient())
            {

                request = new GetProductFeedbackRequest
                {
                    ProductId = new FullyQualifiedProductId
                    {
                        CatalogId = "BaseCatalog",
                        ProductId = "123",
                    },
                    TenantId = TestConstants.TenantId.JTLeigh,
                    CultureId = TestConstants.CultureId.EnglishCanada,
                    EffectiveDate = new DateTime(2008, 06, 01),
                    SelectionBehaviorName = "datedesc",
                };

                response = client.GetProductFeedback(request);

                client.Close();
            }

			// validate the response

			ValidateGetProductFeedbackResponse(response);

			Assert.IsTrue(TryGetProductFeedback(response.Feedback, new Guid("9130AAC0-02B8-4ED0-B1FD-FD7C1C993EE7"), out feedback));
			Assert.AreEqual(TestConstants.CultureId.EnglishCanada, feedback.CultureId);
			Assert.AreEqual(new DateTime(2008, 01, 01), feedback.DateAdded);
			Assert.IsNull(feedback.CustomerId);
			Assert.AreEqual("John Doe", feedback.CustomerName);
			Assert.IsNull(feedback.CustomerLocation);
			Assert.IsNull(feedback.EditorComments);
			Assert.IsNotNull(feedback.Rating);
			Assert.AreEqual(3, feedback.Rating.Value);
			Assert.IsNotNull(feedback.Rating.AttributeValues);
			Assert.AreEqual(2, feedback.Rating.AttributeValues.Count);
			Assert.IsTrue(TryGetProductRatingAttributeValue(feedback.Rating.AttributeValues, Constants.ProductRatingAttribute.AttributeId.ImageQuality, out ratingAttributeValue));
			Assert.AreEqual(3, ratingAttributeValue.Value);
			Assert.IsTrue(TryGetProductRatingAttributeValue(feedback.Rating.AttributeValues, Constants.ProductRatingAttribute.AttributeId.SoundQuality, out ratingAttributeValue));
			Assert.AreEqual(3, ratingAttributeValue.Value);
			Assert.IsNull(feedback.Recommendation);
			// NOTE: no recommendation, so no recommendation attributes
			Assert.IsNotNull(feedback.Review);
			Assert.AreEqual("Good but not great.", feedback.Review.Title);
			Assert.AreEqual("I had high hopes for this product, and while it wasn't a disappointment, it didn't live up to the hype.", feedback.Review.Body);
			Assert.AreEqual(1, feedback.Review.TotalThirdPartyReviews);
			Assert.AreEqual(1, feedback.Review.PositiveThirdPartyReviews);
			// NOTE: no review attributes for this review
			Assert.IsNotNull(feedback.Review.AttributeValues);
			Assert.AreEqual(0, feedback.Review.AttributeValues.Count);
            // NOTE: no review images for this review
            Assert.IsNotNull(feedback.Review.Images);
            Assert.AreEqual(0, feedback.Review.Images.Count);
            // NOTE: no review video for this review
            Assert.IsNull(feedback.Review.Video);

			Assert.IsTrue(TryGetProductFeedback(response.Feedback, new Guid("7E1ABE09-FD0F-404A-B4DC-ADD61EE9E6F1"), out feedback));
			Assert.AreEqual(TestConstants.CultureId.EnglishCanada, feedback.CultureId);
			Assert.AreEqual(new DateTime(2008, 01, 02), feedback.DateAdded);
			Assert.AreEqual(TestConstants.CustomerId.MikeWhite, feedback.CustomerId);
			Assert.AreEqual("Colin Coller", feedback.CustomerName);
			Assert.AreEqual("Toronto, ON", feedback.CustomerLocation);
			Assert.IsNull(feedback.EditorComments);
			Assert.IsNotNull(feedback.Rating);
			Assert.AreEqual(5, feedback.Rating.Value);
			Assert.IsNotNull(feedback.Rating.AttributeValues);
			Assert.AreEqual(2, feedback.Rating.AttributeValues.Count);
			Assert.IsTrue(TryGetProductRatingAttributeValue(feedback.Rating.AttributeValues, Constants.ProductRatingAttribute.AttributeId.ImageQuality, out ratingAttributeValue));
			Assert.AreEqual(4, ratingAttributeValue.Value);
			Assert.IsTrue(TryGetProductRatingAttributeValue(feedback.Rating.AttributeValues, Constants.ProductRatingAttribute.AttributeId.SoundQuality, out ratingAttributeValue));
			Assert.AreEqual(5, ratingAttributeValue.Value);
			Assert.IsNotNull(feedback.Recommendation);
			Assert.IsTrue(feedback.Recommendation.Value);
			Assert.IsNotNull(feedback.Recommendation.AttributeValues);
			Assert.AreEqual(2, feedback.Recommendation.AttributeValues.Count);
			Assert.IsTrue(TryGetProductRecommendationAttributeValue(feedback.Recommendation.AttributeValues, Constants.ProductRecommendationAttribute.AttributeId.FamilyMember, out recommendationAttributeValue));
			Assert.IsTrue(recommendationAttributeValue.Value);
			Assert.IsTrue(TryGetProductRecommendationAttributeValue(feedback.Recommendation.AttributeValues, Constants.ProductRecommendationAttribute.AttributeId.Friend, out recommendationAttributeValue));
			Assert.IsTrue(recommendationAttributeValue.Value);
			Assert.IsNotNull(feedback.Review);
			Assert.AreEqual("Money very well spent!", feedback.Review.Title);
			Assert.AreEqual("This product is excellent.  I'm very glad I spent money on it.  5 stars!", feedback.Review.Body);
			Assert.AreEqual(5, feedback.Review.TotalThirdPartyReviews);
			Assert.AreEqual(5, feedback.Review.PositiveThirdPartyReviews);
			Assert.IsNotNull(feedback.Review.AttributeValues);
			Assert.AreEqual(2, feedback.Review.AttributeValues.Count);
			Assert.IsTrue(TryGetProductReviewAttributeValue(feedback.Review.AttributeValues, Constants.ProductReviewAttribute.AttributeId.Pros, out reviewAttributeValue));
			Assert.AreEqual("Very easy to use.", reviewAttributeValue.Value);
			Assert.IsTrue(TryGetProductReviewAttributeValue(feedback.Review.AttributeValues, Constants.ProductReviewAttribute.AttributeId.Cons, out reviewAttributeValue));
			Assert.AreEqual("Product documentation could be less vague.", reviewAttributeValue.Value);
            Assert.IsNotNull(feedback.Review.Images);
            Assert.AreEqual(2, feedback.Review.Images.Count);
            Assert.IsTrue(TryGetProductReviewImage(feedback.Review.Images, Constants.ProductReviewImage.ImageId.ProductInSunlight, out reviewImage));
            Assert.AreEqual("Product in sunlight", reviewImage.Caption);
            Assert.AreEqual("product-in-sunlight-thumbnail.gif", reviewImage.ThumbnailPath);
            Assert.AreEqual(60, reviewImage.ThumbnailWidth);
            Assert.AreEqual(40, reviewImage.ThumbnailHeight);
            Assert.AreEqual("product-in-sunlight.gif", reviewImage.ImagePath);
            Assert.AreEqual(300, reviewImage.ImageWidth);
            Assert.AreEqual(200, reviewImage.ImageHeight);
            Assert.IsTrue(TryGetProductReviewImage(feedback.Review.Images, Constants.ProductReviewImage.ImageId.ProductInLowLight, out reviewImage));
            Assert.AreEqual("Product in low light", reviewImage.Caption);
            Assert.AreEqual("product-in-low-light-thumbnail.gif", reviewImage.ThumbnailPath);
            Assert.AreEqual(60, reviewImage.ThumbnailWidth);
            Assert.AreEqual(40, reviewImage.ThumbnailHeight);
            Assert.AreEqual("product-in-low-light.gif", reviewImage.ImagePath);
            Assert.AreEqual(300, reviewImage.ImageWidth);
            Assert.AreEqual(200, reviewImage.ImageHeight);
            Assert.IsNotNull(feedback.Review.Video);
            Assert.AreEqual("good-review.gif", feedback.Review.Video.StillPath);
            Assert.AreEqual(60, feedback.Review.Video.StillWidth);
            Assert.AreEqual(40, feedback.Review.Video.StillHeight);
            Assert.AreEqual("good-review.flv", feedback.Review.Video.VideoPath);
            Assert.AreEqual(300, feedback.Review.Video.VideoWidth);
            Assert.AreEqual(200, feedback.Review.Video.VideoHeight);
            Assert.AreEqual(60, feedback.Review.Video.Length);
            Assert.AreEqual("This is my review.", feedback.Review.Video.Transcript);

			Assert.IsTrue(TryGetProductFeedback(response.Feedback, new Guid("8405B4F2-524B-490E-9649-A8FA753CB00E"), out feedback));
			Assert.AreEqual(TestConstants.CultureId.EnglishCanada, feedback.CultureId);
			Assert.AreEqual(new DateTime(2008, 01, 03), feedback.DateAdded);
			Assert.AreEqual(TestConstants.CustomerId.JohnSmith, feedback.CustomerId);
			Assert.AreEqual("John Smith", feedback.CustomerName);
			Assert.AreEqual("Ottawa, ON", feedback.CustomerLocation);
			Assert.AreEqual("Removed profanity.", feedback.EditorComments);
			Assert.IsNotNull(feedback.Rating);
			Assert.AreEqual(0, feedback.Rating.Value);
			Assert.IsNotNull(feedback.Rating.AttributeValues);
			Assert.AreEqual(2, feedback.Rating.AttributeValues.Count);
			Assert.IsTrue(TryGetProductRatingAttributeValue(feedback.Rating.AttributeValues, Constants.ProductRatingAttribute.AttributeId.ImageQuality, out ratingAttributeValue));
			Assert.AreEqual(0, ratingAttributeValue.Value);
			Assert.IsTrue(TryGetProductRatingAttributeValue(feedback.Rating.AttributeValues, Constants.ProductRatingAttribute.AttributeId.SoundQuality, out ratingAttributeValue));
			Assert.AreEqual(0, ratingAttributeValue.Value);
			Assert.IsNotNull(feedback.Recommendation);
			Assert.IsFalse(feedback.Recommendation.Value);
			Assert.IsNotNull(feedback.Recommendation.AttributeValues);
			Assert.AreEqual(2, feedback.Recommendation.AttributeValues.Count);
			Assert.IsTrue(TryGetProductRecommendationAttributeValue(feedback.Recommendation.AttributeValues, Constants.ProductRecommendationAttribute.AttributeId.FamilyMember, out recommendationAttributeValue));
			Assert.IsFalse(recommendationAttributeValue.Value);
			Assert.IsTrue(TryGetProductRecommendationAttributeValue(feedback.Recommendation.AttributeValues, Constants.ProductRecommendationAttribute.AttributeId.Friend, out recommendationAttributeValue));
			Assert.IsFalse(recommendationAttributeValue.Value);
			Assert.IsNotNull(feedback.Review);
			Assert.AreEqual("Completely worthless!", feedback.Review.Title);
			Assert.AreEqual("This product is completely worthless.  It was a total waste of money.  I will never buy from this manufacturer again.", feedback.Review.Body);
			Assert.AreEqual(5, feedback.Review.TotalThirdPartyReviews);
			Assert.AreEqual(0, feedback.Review.PositiveThirdPartyReviews);
			Assert.IsNotNull(feedback.Review.AttributeValues);
			Assert.AreEqual(2, feedback.Review.AttributeValues.Count);
			Assert.IsTrue(TryGetProductReviewAttributeValue(feedback.Review.AttributeValues, Constants.ProductReviewAttribute.AttributeId.Pros, out reviewAttributeValue));
			Assert.AreEqual("None!  This product sucks!", reviewAttributeValue.Value);
			Assert.IsTrue(TryGetProductReviewAttributeValue(feedback.Review.AttributeValues, Constants.ProductReviewAttribute.AttributeId.Cons, out reviewAttributeValue));
            Assert.IsNotNull(feedback.Review.Images);
            Assert.AreEqual(1, feedback.Review.Images.Count);
            Assert.IsTrue(TryGetProductReviewImage(feedback.Review.Images, Constants.ProductReviewImage.ImageId.TerribleQuality, out reviewImage));
            Assert.IsNull(reviewImage.Caption);
            Assert.AreEqual("terrible-quality-thumbnail.gif", reviewImage.ThumbnailPath);
            Assert.AreEqual(50, reviewImage.ThumbnailWidth);
            Assert.AreEqual(40, reviewImage.ThumbnailHeight);
            Assert.AreEqual("terrible-quality.gif", reviewImage.ImagePath);
            Assert.AreEqual(250, reviewImage.ImageWidth);
            Assert.AreEqual(200, reviewImage.ImageHeight);
            Assert.IsNotNull(feedback.Review.Video);
            Assert.AreEqual("terrible-review.gif", feedback.Review.Video.StillPath);
            Assert.AreEqual(50, feedback.Review.Video.StillWidth);
            Assert.AreEqual(40, feedback.Review.Video.StillHeight);
            Assert.AreEqual("terrible-review.flv", feedback.Review.Video.VideoPath);
            Assert.AreEqual(250, feedback.Review.Video.VideoWidth);
            Assert.AreEqual(200, feedback.Review.Video.VideoHeight);
            Assert.AreEqual(120, feedback.Review.Video.Length);
            Assert.IsNull(feedback.Review.Video.Transcript);
            
			Assert.IsTrue(response.RatingAttributes.TryGetValue(Constants.ProductRatingAttribute.AttributeId.ImageQuality, out ratingAttribute));
			Assert.AreEqual(1, ratingAttribute.DisplayOrder);
			Assert.AreEqual("Image quality", ratingAttribute.Text);
			Assert.IsTrue(response.RatingAttributes.TryGetValue(Constants.ProductRatingAttribute.AttributeId.SoundQuality, out ratingAttribute));
			Assert.AreEqual(2, ratingAttribute.DisplayOrder);
			Assert.AreEqual("Sound quality", ratingAttribute.Text);

			Assert.IsTrue(response.RecommendationAttributes.TryGetValue(Constants.ProductRecommendationAttribute.AttributeId.FamilyMember, out recommendationAttribute));
			Assert.AreEqual(1, recommendationAttribute.DisplayOrder);
			Assert.AreEqual("...to a family member", recommendationAttribute.Text);
			Assert.IsTrue(response.RecommendationAttributes.TryGetValue(Constants.ProductRecommendationAttribute.AttributeId.Friend, out recommendationAttribute));
			Assert.AreEqual(2, recommendationAttribute.DisplayOrder);
			Assert.AreEqual("...to a friend", recommendationAttribute.Text);

			Assert.IsTrue(response.ReviewAttributes.TryGetValue(Constants.ProductReviewAttribute.AttributeId.Pros, out reviewAttribute));
			Assert.AreEqual(1, reviewAttribute.DisplayOrder);
			Assert.AreEqual("Pros", reviewAttribute.Text);
			Assert.IsTrue(response.ReviewAttributes.TryGetValue(Constants.ProductReviewAttribute.AttributeId.Cons, out reviewAttribute));
			Assert.AreEqual(2, reviewAttribute.DisplayOrder);
			Assert.AreEqual("Cons", reviewAttribute.Text);

		}

        /// <summary>
        /// FIXME
        /// </summary>
		[TestMethod]
		public void TestGetProductFeedbackFrench()
		{
			ProductFeedbackRuntimeServiceClient client;
			GetProductFeedbackRequest request;
			GetProductFeedbackResponse response;
			ProductFeedback feedback;
			ProductRatingAttributeValue ratingAttributeValue;
			ProductRecommendationAttributeValue recommendationAttributeValue;
			ProductReviewAttributeValue reviewAttributeValue;
			GetProductFeedback_ProductRatingAttribute ratingAttribute;
			GetProductFeedback_ProductRecommendationAttribute recommendationAttribute;
			ProductReviewAttribute reviewAttribute;

            using (client = new ProductFeedbackRuntimeServiceClient())
            {

                request = new GetProductFeedbackRequest
                {
                    ProductId = new FullyQualifiedProductId
                    {
                        CatalogId = "BaseCatalog",
                        ProductId = "456",
                    },
                    TenantId = TestConstants.TenantId.JTLeigh,
                    CultureId = TestConstants.CultureId.FrenchCanada,
                    EffectiveDate = new DateTime(2008, 06, 01),
                    SelectionBehaviorName = "datedesc",
                };

                response = client.GetProductFeedback(request);

                client.Close();
            }

			// validate the response

			ValidateGetProductFeedbackResponse(response);

			Assert.IsTrue(TryGetProductFeedback(response.Feedback, new Guid("CF8F7901-6F71-435c-A43A-748EC1E0A029"), out feedback));
			Assert.AreEqual(TestConstants.CultureId.FrenchCanada, feedback.CultureId);
			Assert.AreEqual(new DateTime(2008, 01, 01), feedback.DateAdded);
			Assert.AreEqual(TestConstants.CustomerId.JeanFrancoisLyon, feedback.CustomerId);
			Assert.AreEqual("Jean Francois Lyon", feedback.CustomerName);
			Assert.AreEqual("Montreal, QC", feedback.CustomerLocation);
			Assert.IsNull(feedback.EditorComments);
			Assert.IsNotNull(feedback.Rating);
			Assert.AreEqual(2, feedback.Rating.Value);
			Assert.IsNotNull(feedback.Rating.AttributeValues);
			Assert.AreEqual(2, feedback.Rating.AttributeValues.Count);
			Assert.IsTrue(TryGetProductRatingAttributeValue(feedback.Rating.AttributeValues, Constants.ProductRatingAttribute.AttributeId.ValueForMoney, out ratingAttributeValue));
			Assert.AreEqual(3, ratingAttributeValue.Value);
			Assert.IsTrue(TryGetProductRatingAttributeValue(feedback.Rating.AttributeValues, Constants.ProductRatingAttribute.AttributeId.Design, out ratingAttributeValue));
			Assert.AreEqual(2, ratingAttributeValue.Value);
			Assert.IsNotNull(feedback.Recommendation);
			Assert.IsTrue(feedback.Recommendation.Value);
			Assert.IsNotNull(feedback.Recommendation.AttributeValues);
			Assert.AreEqual(1, feedback.Recommendation.AttributeValues.Count);
			Assert.IsTrue(TryGetProductRecommendationAttributeValue(feedback.Recommendation.AttributeValues, Constants.ProductRecommendationAttribute.AttributeId.Coworker, out recommendationAttributeValue));
			Assert.IsTrue(recommendationAttributeValue.Value);
			Assert.IsNotNull(feedback.Review);
			Assert.AreEqual("C'est un très bon produit.", feedback.Review.Title);
			Assert.AreEqual("Longue durabilité de la batterie, dimensions miniature de l'appareil, petite pince très pratique... ce sont toutes des qualités de produit.", feedback.Review.Body);
			Assert.AreEqual(3, feedback.Review.TotalThirdPartyReviews);
			Assert.AreEqual(2, feedback.Review.PositiveThirdPartyReviews);
			Assert.IsNotNull(feedback.Review.AttributeValues);
			Assert.AreEqual(1, feedback.Review.AttributeValues.Count);
			Assert.IsTrue(TryGetProductReviewAttributeValue(feedback.Review.AttributeValues, Constants.ProductReviewAttribute.AttributeId.BottomLine, out reviewAttributeValue));
			Assert.AreEqual("Très bon produit.", reviewAttributeValue.Value);
            // NOTE: no review images for this review
            Assert.IsNotNull(feedback.Review.Images);
            Assert.AreEqual(0, feedback.Review.Images.Count);
            // NOTE: no review video for this review
            Assert.IsNull(feedback.Review.Video);

			Assert.IsTrue(response.RatingAttributes.TryGetValue(Constants.ProductRatingAttribute.AttributeId.ValueForMoney, out ratingAttribute));
			Assert.AreEqual(1, ratingAttribute.DisplayOrder);
			Assert.AreEqual("Valeur l'argent", ratingAttribute.Text);
			Assert.IsTrue(response.RatingAttributes.TryGetValue(Constants.ProductRatingAttribute.AttributeId.Design, out ratingAttribute));
			Assert.AreEqual(2, ratingAttribute.DisplayOrder);
			Assert.AreEqual("Conception", ratingAttribute.Text);

			Assert.IsTrue(response.RecommendationAttributes.TryGetValue(Constants.ProductRecommendationAttribute.AttributeId.Coworker, out recommendationAttribute));
			Assert.AreEqual(2, recommendationAttribute.DisplayOrder); // NOTE: This attribute has a display order of 2 from June 1st through July 1st.
			Assert.AreEqual("...à un collègue", recommendationAttribute.Text);

			Assert.IsTrue(response.ReviewAttributes.TryGetValue(Constants.ProductReviewAttribute.AttributeId.BottomLine, out reviewAttribute));
			Assert.AreEqual(2, reviewAttribute.DisplayOrder); // NOTE: This attribute has a display order of 2 from June 1st through July 1st.
			Assert.AreEqual("Générale", reviewAttribute.Text);

		}

        /// <summary>
        /// FIXME
        /// </summary>
		[TestMethod]
		public void TestGetProductFeedbackSnapshotEnglish()
		{
			ProductFeedbackRuntimeServiceClient client;
			GetProductFeedbackSnapshotRequest request;
			GetProductFeedbackSnapshotResponse response;
			GetProductFeedbackSnapshot_ProductRatingAttribute ratingAttribute;
			GetProductFeedbackSnapshot_ProductRecommendationAttribute recommendationAttribute;

            using (client = new ProductFeedbackRuntimeServiceClient())
            {

                request = new GetProductFeedbackSnapshotRequest
                {
                    ProductId = new FullyQualifiedProductId
                    {
                        CatalogId = "BaseCatalog",
                        ProductId = "123",
                    },
                    TenantId = TestConstants.TenantId.JTLeigh,
                    CultureId = TestConstants.CultureId.EnglishCanada,
                    EffectiveDate = new DateTime(2008, 06, 01),
                    SelectionBehaviorName = "datedesc",
                };

                response = client.GetProductFeedbackSnapshot(request);

                client.Close();
            }

			// validate the response

			ValidateGetProductFeedbackSnapshotResponse(response);

			Assert.AreEqual(3, response.Snapshot.TotalRatings);
			Assert.AreEqual(2.67d, Math.Round(response.Snapshot.AverageRatingValue.Value, 2));
			Assert.AreEqual(2, response.Snapshot.TotalRecommendations);
			Assert.AreEqual(1, response.Snapshot.PositiveRecommendations);
			Assert.AreEqual(3, response.Snapshot.TotalReviews);

			Assert.AreEqual(3, response.Snapshot.RatingValueBreakdown.Count);
			Assert.AreEqual(1, response.Snapshot.RatingValueBreakdown[0]);
			Assert.AreEqual(1, response.Snapshot.RatingValueBreakdown[3]);
			Assert.AreEqual(1, response.Snapshot.RatingValueBreakdown[5]);

			Assert.AreEqual(2, response.Snapshot.AverageRatingAttributeValues.Count);
			Assert.AreEqual(2.33d, Math.Round(response.Snapshot.AverageRatingAttributeValues[Constants.ProductRatingAttribute.AttributeId.ImageQuality], 2));
			Assert.AreEqual(2.67d, Math.Round(response.Snapshot.AverageRatingAttributeValues[Constants.ProductRatingAttribute.AttributeId.SoundQuality], 2));

			Assert.AreEqual(2, response.Snapshot.TotalRecommendationAttributeValues.Count);
			Assert.AreEqual(2, response.Snapshot.TotalRecommendationAttributeValues[Constants.ProductRecommendationAttribute.AttributeId.Friend]);
			Assert.AreEqual(2, response.Snapshot.TotalRecommendationAttributeValues[Constants.ProductRecommendationAttribute.AttributeId.FamilyMember]);

			Assert.AreEqual(2, response.Snapshot.PositiveRecommendationAttributeValues.Count);
			Assert.AreEqual(1, response.Snapshot.PositiveRecommendationAttributeValues[Constants.ProductRecommendationAttribute.AttributeId.Friend]);
			Assert.AreEqual(1, response.Snapshot.PositiveRecommendationAttributeValues[Constants.ProductRecommendationAttribute.AttributeId.FamilyMember]);

			Assert.IsTrue(response.RatingAttributes.TryGetValue(Constants.ProductRatingAttribute.AttributeId.ImageQuality, out ratingAttribute));
			Assert.AreEqual(1, ratingAttribute.DisplayOrder);
			Assert.AreEqual("Image quality", ratingAttribute.Text);
			Assert.IsTrue(response.RatingAttributes.TryGetValue(Constants.ProductRatingAttribute.AttributeId.SoundQuality, out ratingAttribute));
			Assert.AreEqual(2, ratingAttribute.DisplayOrder);
			Assert.AreEqual("Sound quality", ratingAttribute.Text);

			Assert.IsTrue(response.RecommendationAttributes.TryGetValue(Constants.ProductRecommendationAttribute.AttributeId.FamilyMember, out recommendationAttribute));
			Assert.AreEqual(1, recommendationAttribute.DisplayOrder);
			Assert.AreEqual("...to a family member", recommendationAttribute.Text);
			Assert.IsTrue(response.RecommendationAttributes.TryGetValue(Constants.ProductRecommendationAttribute.AttributeId.Friend, out recommendationAttribute));
			Assert.AreEqual(2, recommendationAttribute.DisplayOrder);
			Assert.AreEqual("...to a friend", recommendationAttribute.Text);

		}

        /// <summary>
        /// FIXME
        /// </summary>
        [TestMethod]
		public void TestGetProductFeedbackSnapshotFrench()
		{
			ProductFeedbackRuntimeServiceClient client;
			GetProductFeedbackSnapshotRequest request;
			GetProductFeedbackSnapshotResponse response;
			GetProductFeedbackSnapshot_ProductRatingAttribute ratingAttribute;
			GetProductFeedbackSnapshot_ProductRecommendationAttribute recommendationAttribute;

            using (client = new ProductFeedbackRuntimeServiceClient())
            {

                request = new GetProductFeedbackSnapshotRequest
                {
                    ProductId = new FullyQualifiedProductId
                    {
                        CatalogId = "BaseCatalog",
                        ProductId = "456",
                    },
                    TenantId = TestConstants.TenantId.JTLeigh,
                    CultureId = TestConstants.CultureId.FrenchCanada,
                    EffectiveDate = new DateTime(2008, 06, 01),
                    SelectionBehaviorName = "datedesc",
                };

                response = client.GetProductFeedbackSnapshot(request);

                client.Close();
            }

			// validate the response

			ValidateGetProductFeedbackSnapshotResponse(response);

			Assert.AreEqual(1, response.Snapshot.TotalRatings);
			Assert.AreEqual(2.00d, Math.Round(response.Snapshot.AverageRatingValue.Value, 2));
			Assert.AreEqual(1, response.Snapshot.TotalRecommendations);
			Assert.AreEqual(1, response.Snapshot.PositiveRecommendations);
			Assert.AreEqual(1, response.Snapshot.TotalReviews);

			Assert.AreEqual(1, response.Snapshot.RatingValueBreakdown.Count);
			Assert.AreEqual(1, response.Snapshot.RatingValueBreakdown[2]);

			Assert.AreEqual(2, response.Snapshot.AverageRatingAttributeValues.Count);
			Assert.AreEqual(3.00d, Math.Round(response.Snapshot.AverageRatingAttributeValues[Constants.ProductRatingAttribute.AttributeId.ValueForMoney], 2));
			Assert.AreEqual(2.00d, Math.Round(response.Snapshot.AverageRatingAttributeValues[Constants.ProductRatingAttribute.AttributeId.Design], 2));

			Assert.AreEqual(1, response.Snapshot.TotalRecommendationAttributeValues.Count);
			Assert.AreEqual(1, response.Snapshot.TotalRecommendationAttributeValues[Constants.ProductRecommendationAttribute.AttributeId.Coworker]);

			Assert.AreEqual(1, response.Snapshot.PositiveRecommendationAttributeValues.Count);
			Assert.AreEqual(1, response.Snapshot.PositiveRecommendationAttributeValues[Constants.ProductRecommendationAttribute.AttributeId.Coworker]);

			Assert.IsTrue(response.RatingAttributes.TryGetValue(Constants.ProductRatingAttribute.AttributeId.ValueForMoney, out ratingAttribute));
			Assert.AreEqual(1, ratingAttribute.DisplayOrder);
			Assert.AreEqual("Valeur l'argent", ratingAttribute.Text);
			Assert.IsTrue(response.RatingAttributes.TryGetValue(Constants.ProductRatingAttribute.AttributeId.Design, out ratingAttribute));
			Assert.AreEqual(2, ratingAttribute.DisplayOrder);
			Assert.AreEqual("Conception", ratingAttribute.Text);

			Assert.IsTrue(response.RecommendationAttributes.TryGetValue(Constants.ProductRecommendationAttribute.AttributeId.Coworker, out recommendationAttribute));
			Assert.AreEqual(2, recommendationAttribute.DisplayOrder); // NOTE: This attribute has a display order of 2 from June 1st through July 1st.
			Assert.AreEqual("...à un collègue", recommendationAttribute.Text);

		}

        /// <summary>
        /// FIXME
        /// </summary>
        [TestMethod]
		public void TestGetProductFeedbackSummaries()
		{
			// NOTE: GetProductFeedbackSummaries currently isn't culture-specific, so we don't need 
			// English and French versions of the test.

			ProductFeedbackRuntimeServiceClient client;
			GetProductFeedbackSummariesRequest request;
			GetProductFeedbackSummariesResponse response;
			ProductFeedbackSummary summary;

            using (client = new ProductFeedbackRuntimeServiceClient())
            {

                request = new GetProductFeedbackSummariesRequest
                {
                    ProductIds = new List<FullyQualifiedProductId>
				{
					new FullyQualifiedProductId
                    {
                        CatalogId = "BaseCatalog",
                        ProductId = "123",
                    },
					new FullyQualifiedProductId
                    {
                        CatalogId = "BaseCatalog",
                        ProductId = "456",
                    },
                    new FullyQualifiedProductId
                    {
                        CatalogId = "BaseCatalog",
    					ProductId = "789",
                    },
				},
                    TenantId = TestConstants.TenantId.JTLeigh,
                    CultureId = TestConstants.CultureId.EnglishCanada,
                    EffectiveDate = new DateTime(2008, 06, 01),
                    SelectionBehaviorName = "datedesc",
                };

                response = client.GetProductFeedbackSummaries(request);

                client.Close();
            }

			// validate the response

			ValidateGetProductFeedbackSummariesResponse(response);

			Assert.AreEqual(3, response.Summaries.Count);

            Assert.IsTrue(response.Summaries.TryGetValue(new FullyQualifiedProductId { CatalogId = "BaseCatalog", ProductId = "123", }, out summary));
			Assert.AreEqual(3, summary.TotalRatings);
			Assert.AreEqual(2.67d, Math.Round(summary.AverageRatingValue.Value, 2));
			Assert.AreEqual(2, summary.TotalRecommendations);
			Assert.AreEqual(1, summary.PositiveRecommendations);
			Assert.AreEqual(3, summary.TotalReviews);

            Assert.IsTrue(response.Summaries.TryGetValue(new FullyQualifiedProductId { CatalogId = "BaseCatalog", ProductId = "456", }, out summary));
			Assert.AreEqual(1, summary.TotalRatings);
			Assert.AreEqual(2.00d, Math.Round(summary.AverageRatingValue.Value, 2));
			Assert.AreEqual(1, summary.TotalRecommendations);
			Assert.AreEqual(1, summary.PositiveRecommendations);
			Assert.AreEqual(1, summary.TotalReviews);

			Assert.IsTrue(response.Summaries.TryGetValue(new FullyQualifiedProductId { CatalogId = "BaseCatalog", ProductId = "789", }, out summary));
			Assert.AreEqual(0, summary.TotalRatings);
			Assert.IsNull(summary.AverageRatingValue);
			Assert.AreEqual(0, summary.TotalRecommendations);
			Assert.AreEqual(0, summary.PositiveRecommendations);
			Assert.AreEqual(0, summary.TotalReviews);
		}

		#endregion // Methods

		#region Implementation

		private static void ValidateGetProductFeedbackResponse(GetProductFeedbackResponse response)
		{

			// all collections must not be null
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Feedback);
			Assert.IsNotNull(response.RatingAttributes);
			Assert.IsNotNull(response.RecommendationAttributes);
			Assert.IsNotNull(response.ReviewAttributes);

			foreach (ProductFeedback feedback in response.Feedback)
			{
				if (feedback.Rating != null)
				{

					// all sub-collections must not be null
					Assert.IsNotNull(feedback.Rating.AttributeValues);

					// all rating attributes referred to by rating attribute values must appear in the rating attributes collection
					foreach (ProductRatingAttributeValue attributeValue in feedback.Rating.AttributeValues)
					{
						Assert.IsTrue(response.RatingAttributes.ContainsKey(attributeValue.AttributeId), "response.Feedback[n].Rating.AttributeValues contains value for attribute {0} (\"{1}\"), but response.RatingAttributes doesn't contain that attribute.", attributeValue.AttributeId, attributeValue.Value);
					}

				}
				if (feedback.Recommendation != null)
				{

					// all sub-collections must not be null
					Assert.IsNotNull(feedback.Recommendation.AttributeValues);

					// all recommendation attributes referred to by recommendation attribute values must appear in the recommendation attributes collection
					foreach (ProductRecommendationAttributeValue attributeValue in feedback.Recommendation.AttributeValues)
					{
						Assert.IsTrue(response.RecommendationAttributes.ContainsKey(attributeValue.AttributeId), "response.Feedback[n].Recommendation.AttributeValues contains value for attribute {0} (\"{1}\"), but response.RecommendationAttributes doesn't contain that attribute.", attributeValue.AttributeId, attributeValue.Value);
					}

				}
				if (feedback.Review != null)
				{

					// all sub-collections must not be null
					Assert.IsNotNull(feedback.Review.AttributeValues);

					// all review attributes referred to by review attribute values must appear in the review attributes collection
					foreach (ProductReviewAttributeValue attributeValue in feedback.Review.AttributeValues)
					{
						Assert.IsTrue(response.ReviewAttributes.ContainsKey(attributeValue.AttributeId), "response.Feedback[n].Review.AttributeValues contains value for attribute {0} (\"{1}\"), but response.ReviewAttributes doesn't contain that attribute.", attributeValue.AttributeId, attributeValue.Value);
					}

				}
			}

		}

		private static void ValidateGetProductFeedbackSnapshotResponse(GetProductFeedbackSnapshotResponse response)
		{

			// all collections must not be null
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Snapshot);
			Assert.IsNotNull(response.RatingAttributes);
			Assert.IsNotNull(response.RecommendationAttributes);

			// all subcollections must not be null
			Assert.IsNotNull(response.Snapshot.AverageRatingAttributeValues);
			Assert.IsNotNull(response.Snapshot.TotalRecommendationAttributeValues);
				Assert.IsNotNull(response.Snapshot.PositiveRecommendationAttributeValues);

			// all rating attributes referred to by rating attribute values must appear in the 
			// rating attributes collection
			foreach (Guid attributeId in response.Snapshot.AverageRatingAttributeValues.Keys)
			{
				Assert.IsTrue(response.RatingAttributes.ContainsKey(attributeId), "response.Snapshot.AverageRatingAttributeValues contains value for attribute {0}, but response.RatingAttributes doesn't contain that attribute.", attributeId);
			}

			// all recommendation attributes referred to by total recommendation attribute 
			// values must appear in the recommendation attributes collection
			foreach (Guid attributeId in response.Snapshot.TotalRecommendationAttributeValues.Keys)
			{
				Assert.IsTrue(response.RecommendationAttributes.ContainsKey(attributeId), "response.Snapshot.TotalRecommendationAttributeValues contains value for attribute {0}, but response.RecommendationAttributes doesn't contain that attribute.", attributeId);
			}

			// all recommendation attributes referred to by positive recommendation attribute 
			// values must appear both in the recommendation attributes collection *and* the total 
			// recommendation attribute value collection
			foreach (Guid attributeId in response.Snapshot.PositiveRecommendationAttributeValues.Keys)
			{
				Assert.IsTrue(response.RecommendationAttributes.ContainsKey(attributeId), "response.Snapshot.PositiveRecommendationAttributeValues contains value for attribute {0}, but response.RecommendationAttributes doesn't contain that attribute.", attributeId);
				Assert.IsTrue(response.Snapshot.TotalRecommendationAttributeValues.ContainsKey(attributeId), "response.Snapshot.PositiveRecommendationAttributeValues contains value for attribute {0}, but response.Snapshot.TotalRecommendationAttributeValues doesn't contain that attribute.", attributeId);
			}

		}

		private static void ValidateGetProductFeedbackSummariesResponse(GetProductFeedbackSummariesResponse response)
		{

			// all collections must not be null
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Summaries);

		}

		private static bool TryGetProductFeedback(IList<ProductFeedback> feedbackCollection, Guid feedbackId, out ProductFeedback result)
		{
			foreach (ProductFeedback feedback in feedbackCollection)
			{
				if (feedback.FeedbackId.Equals(feedbackId))
				{
					result = feedback;
					return true;
				}
			}
			result = null;
			return false;
		}

        private static bool TryGetProductRatingAttributeValue(IList<ProductRatingAttributeValue> valueCollection, Guid attributeId, out ProductRatingAttributeValue result)
		{
			foreach (ProductRatingAttributeValue value in valueCollection)
			{
				if (value.AttributeId.Equals(attributeId))
				{
					result = value;
					return true;
				}
			}
			result = null;
			return false;
		}

		private static bool TryGetProductRecommendationAttributeValue(IList<ProductRecommendationAttributeValue> valueCollection, Guid attributeId, out ProductRecommendationAttributeValue result)
		{
			foreach (ProductRecommendationAttributeValue value in valueCollection)
			{
				if (value.AttributeId.Equals(attributeId))
				{
					result = value;
					return true;
				}
			}
			result = null;
			return false;
		}

		private static bool TryGetProductReviewAttributeValue(IList<ProductReviewAttributeValue> valueCollection, Guid attributeId, out ProductReviewAttributeValue result)
		{
			foreach (ProductReviewAttributeValue value in valueCollection)
			{
				if (value.AttributeId.Equals(attributeId))
				{
					result = value;
					return true;
				}
			}
			result = null;
			return false;
		}

        private static bool TryGetProductReviewImage(IList<ProductReviewImage> valueCollection, Guid imageId, out ProductReviewImage result)
        {
            foreach (ProductReviewImage value in valueCollection)
            {
                if (value.ImageId.Equals(imageId))
                {
                    result = value;
                    return true;
                }
            }
            result = null;
            return false;
        }

        #endregion // Implementation

	}

}
